package vincent.com.layouttest.adapter;

import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import vincent.com.layouttest.BluetoothActivity;
import vincent.com.layouttest.R;
import vincent.com.layouttest.util.LogUtil;
import vincent.com.layouttest.util.ReflectHelper;

/**
 * Created by zhengwenchen on 2016/12/16.
 */
public class BluetoothDeviceAdapter extends BaseAdapter implements View.OnClickListener, BluetoothActivity.OnProfileChangeListener {
    public static final int AVAIL_LIST_TYPE = 1;
    public static final int BONDED_LIST_TYPE= 2;

    private int type;

    private Context mContext;
    private List<BluetoothDevice> mData = new ArrayList<>();

    private String mConnectedAddress;

    private BluetoothHeadset mHeadsetService;
    private BluetoothA2dp mA2dpService;

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public BluetoothDeviceAdapter(Context ctx, List<BluetoothDevice> data, int type){
        this.mContext = ctx;
        this.mData = data;
        this.type = type;
    }

    public BluetoothDeviceAdapter(Context ctx, int type){
        this.mContext = ctx;
        this.type = type;
    }


    public void setData(List<BluetoothDevice> data){
        this.mData.clear();
        this.mData.addAll(data);
        notifyDataSetChanged();
    }

    public void setData(BluetoothDevice[] devices){
        this.mData.clear();
        Collections.addAll(this.mData, devices);

        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mData != null ? mData.size() : 0;
    }

    @Override
    public Object getItem(int position) {
        return (mData != null && position < mData.size()) ? mData.get(position) : null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View view;
        ViewHolder holder;

        if(convertView == null){
            view = LayoutInflater.from(mContext).inflate(R.layout.bluetooth_adapter_item, parent, false);

            holder = new ViewHolder(view);

            if(BONDED_LIST_TYPE == type){
                holder.close.setVisibility(View.VISIBLE);
                holder.close.setOnClickListener(this);
            }else{
                holder.close.setVisibility(View.GONE);
            }

            view.setTag(holder);
        }else{
            view = convertView;
            holder = (ViewHolder)view.getTag();
        }

        if(BONDED_LIST_TYPE == type){
            holder.close.setTag(position);
        }

        BluetoothDevice device = mData.get(position);
        BluetoothClass btClass = device.getBluetoothClass();

        holder.icon.setImageResource(getDrawable(btClass));

        if(device.getAddress().equals(mConnectedAddress)){
            holder.state.setText("已连接");
        }else{
            holder.state.setText("");
        }

        if(device != null){
            if(!TextUtils.isEmpty(device.getName())){
                holder.name.setText(device.getName());
            }else{
                holder.name.setText(device.getAddress());
            }
        }

        return view;
    }

    @Override
    public void onClick(View v) {
        int position = (int) v.getTag();
        BluetoothDevice dev = (BluetoothDevice) getItem(position);
        if(dev != null){
            removeBond(dev);
        }
    }

    public void removeBond(BluetoothDevice device){
        LogUtil.i("czw_bluetooth", "移除配对");
        ReflectHelper.callDeclaredMethod(device, "removeBond", null, null);
    }

    @Override
    public void onServiceConnected(int profile, BluetoothProfile proxy) {

        if(BluetoothProfile.HEADSET == profile){
            mHeadsetService = (BluetoothHeadset) proxy;
        }else if(BluetoothProfile.A2DP == profile){
            mA2dpService = (BluetoothA2dp) proxy;
        }
    }

    @Override
    public void onServiceDisconnected(int profile) {
        if(BluetoothProfile.HEADSET == profile){
            mHeadsetService = null;
        }else if(BluetoothProfile.A2DP == profile){
            mA2dpService = null;
        }
    }

    @Override
    public void onDestory() {
        mA2dpService = null;
        mHeadsetService = null;
    }

    static class ViewHolder{

        ViewHolder(View view){
            name = (TextView) view.findViewById(R.id.name);
            state = (TextView) view.findViewById(R.id.state);
            close = (ImageView)view.findViewById(R.id.close_btn);
            icon = (ImageView)view.findViewById(R.id.icon);
        }
        TextView name;
        TextView state;
        ImageView close;
        ImageView icon;
    }

    public void clear(){
        this.mData.clear();
        notifyDataSetChanged();
    }

    public void addDevice(BluetoothDevice dev){
        for(BluetoothDevice device : mData){
            if(device.getAddress().equals(dev.getAddress())){
                return;
            }
        }

        this.mData.add(dev);
        notifyDataSetChanged();
    }

    public void updateConnectedAddress(String address){
        this.mConnectedAddress = address;
        notifyDataSetChanged();
    }

    public void clearConnectAddress(BluetoothDevice device){

        if(device.getAddress().equals(this.mConnectedAddress)){
            this.mConnectedAddress = "";
        }
        notifyDataSetChanged();
    }

    public void removeDevice(BluetoothDevice device){
        if(mData.size() > 0){

            for(BluetoothDevice dev : mData){
                if(device.getAddress().equals(dev.getAddress())){
                    mData.remove(dev);
                    notifyDataSetChanged();
                    break;
                }
            }
        }
    }

    public int getDrawable(BluetoothClass btClass){
        return getBtClassDrawable(btClass);
    }

    private int getBtClassDrawable(BluetoothClass btClass) {
        if (btClass != null) {
            switch (btClass.getMajorDeviceClass()) {
                case BluetoothClass.Device.Major.COMPUTER:
                    return R.drawable.ic_bt_laptop;

                case BluetoothClass.Device.Major.PHONE:
                    return R.drawable.ic_bt_cellphone;

                case BluetoothClass.Device.Major.PERIPHERAL:
                    return getHidClassDrawable(btClass);

                case BluetoothClass.Device.Major.IMAGING:
                    return R.drawable.ic_bt_imaging;

                default:
                    // unrecognized device class; continue
                    LogUtil.i("czw_bluetooth", "unrecognized device class " + btClass);
            }
        }

        if(mHeadsetService != null){
            return R.drawable.ic_bt_headset_hfp;
        }

        if(mA2dpService != null){
            return R.drawable.ic_bt_headphones_a2dp;
        }

        return R.drawable.ic_settings_bluetooth2;
    }

    int getHidClassDrawable(BluetoothClass btClass) {

        int PERIPHERAL_KEYBOARD = (int)ReflectHelper.getStaticFieldValue(BluetoothClass.Device.class, "PERIPHERAL_KEYBOARD");
        int PERIPHERAL_KEYBOARD_POINTING = (int)ReflectHelper.getStaticFieldValue(BluetoothClass.Device.class, "PERIPHERAL_KEYBOARD_POINTING");
        int PERIPHERAL_POINTING = (int)ReflectHelper.getStaticFieldValue(BluetoothClass.Device.class, "PERIPHERAL_POINTING");

        int devClass = btClass.getDeviceClass();

        if(PERIPHERAL_KEYBOARD == devClass || PERIPHERAL_KEYBOARD_POINTING == devClass){
            return R.drawable.ic_lockscreen_ime;
        }else if(PERIPHERAL_POINTING == devClass){
            return R.drawable.ic_bt_pointing_hid;
        }else{
            return R.drawable.ic_bt_misc_hid;
        }
    }
}
